/* Copyright 2012 Tobias Marschall
 *
 * This file is part of CLEVER.
 *
 * CLEVER is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * CLEVER is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with CLEVER.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <boost/math/distributions.hpp>

#include "Distributions.h"

#include "SumOfBinomials.h"

using namespace std;

SumOfBinomials::SumOfBinomials() : dist(0), offset(0), n(0) {
	dist = new vector<double>(1, 1.0);
}

SumOfBinomials::~SumOfBinomials() {
	if (dist != 0) {
		delete dist;
	}
}

void SumOfBinomials::add(double p, int n) {
	assert(dist != 0);
	boost::math::binomial_distribution<> boost_d(n, p);
	vector<double> d;
	for (int k=0; k<=n; ++k) {
		d.push_back(boost::math::pdf(boost_d,k));
	}
	int new_offset;
	auto_ptr<vector<double> > new_dist = Distributions::convolve(*(this->dist), d, this->offset, 0, &new_offset);
	this->offset = new_offset;
	delete dist;
	dist = new_dist.release();
	this->n += n;
}

double SumOfBinomials::probability(int k) {
	assert(k>=0);
	assert(k<=n);
	if ((k<offset) || (k-offset>=dist->size())) {
		return 0.0;
	}
	return dist->at(k-offset);
}
